home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 355_02 / slk2.exe / SPP / DCL.C next >
C/C++ Source or Header  |  1991-06-09  |  16KB  |  795 lines

  1. /*
  2.     Shelock Preprocessor -- Part II -- Declaration parsing routines.
  3.  
  4.     Source: dcl.c
  5.     Started: September 26, 1987
  6.     Version:
  7.         May 24, 1988
  8.         February 16, 1989
  9.             periods removed from error messages.
  10.             Spurious warning removed from type_ntail().
  11.             Set prev_dcl = 0 to get rid of error message.
  12.         June 22, 1989
  13.             Bug fix in type_tail().
  14.             curly_ok_flag kludge in i_list().
  15.  
  16.  
  17.     PUBLIC DOMAIN SOFTWARE
  18.  
  19.     Sherlock, including the SPP, SDEL and SDIF programs, was placed in
  20.     the public domain on June 15, 1991, by its author,
  21.  
  22.         Edward K. Ream
  23.         166 North Prospect Ave.
  24.         Madison, WI 53705.
  25.         (608) 257-0802
  26.  
  27.     Sherlock may be used for any commercial or non-commercial purpose.
  28.  
  29.  
  30.     DISCLAIMER OF WARRANTIES
  31.  
  32.     Edward K. Ream (Ream) specifically disclaims all warranties,
  33.     expressed or implied, with respect to this computer software,
  34.     including but not limited to implied warranties of merchantability
  35.     and fitness for a particular purpose.  In no event shall Ream be
  36.     liable for any loss of profit or any commercial damage, including
  37.     but not limited to special, incidental consequential or other damages.
  38. */
  39.  
  40. #include "spp.h"
  41.  
  42. /* Declare local routines of this file. */
  43. static void    array        (void);
  44. static void    dcl_enum    (void);
  45. static void    dcl_struct    (void);
  46. static void    fp_list        (en_scope);
  47. static void    function    (en_scope);
  48. static void    initializer    (void);
  49. static void    i_list        (void);
  50. static void    t_list        (void);
  51. static bool    type_head    (en_scope scope);
  52. static en_tokens type_tail    (en_scope scope);
  53. static void    type_ntail    (void);
  54.  
  55.  
  56. /* =============== Global variables =============== */
  57.  
  58. /* Indicates inside function definition. Used by function() and dcl().      */
  59. /* Set to FALSE by program.  Set to true by function().              */
  60. static bool    func_def;    /* TRUE if a function DEFINTION was seen. */
  61.  
  62. /* Used by function() to see whether function def should give a warning.  */
  63. static int    prev_dcl;    /* Number of previous sub-declarations.    */
  64.  
  65. /* =============== Global routines =============== */
  66.  
  67. /*
  68.     Parse the local variables of a block.
  69. */
  70. void
  71. block_dcls(void)
  72. {
  73.     SL_NAME(fn_name, "block_dcls");
  74.     TRACETOK(fn_name);
  75.  
  76.     while (is_type()) {
  77.         dcl(BLOCK_SCOPE);
  78.     }
  79.  
  80.     RETURN_VOID(fn_name);
  81. }
  82.  
  83. /*
  84.     Parse a single declaration or function definition.
  85.     Semicolon ends a declaration but not a function definition.
  86. */
  87. void
  88. dcl(en_scope scope)
  89. {
  90.     SL_NAME(fn_name, "dcl");
  91.     TRACETOK(fn_name);
  92.     TRACEPN(fn_name, printf("(%s)\n", pr_scope(scope)));
  93.  
  94.     /* Reset semantics for a new declaration. */
  95.     sd_dcl(scope);
  96.  
  97.     allow_mkeys();
  98.     if (type_head(scope) == TRUE) {
  99.         if (func_def && scope == OUTER_SCOPE) {
  100.             /* We saw a bare function definition. */
  101.             TRACEP(fn_name, printf("bare function complete\n"));
  102.  
  103.             prev_dcl = 0;
  104.             RETURN_VOID(fn_name);
  105.         }
  106.         else {
  107.             /* We saw a stand-alone struct\union or enum. */
  108.             must(SEMICOLON_TOK);
  109.             RETURN_VOID(fn_name);
  110.         }
  111.     }
  112.  
  113.     /* 2/16/89 */
  114.     for (prev_dcl = 0; ;) {
  115.  
  116.         type_tail(scope);
  117.         if (scope == OUTER_SCOPE && func_def) {
  118.             /* We ARE at the end of the dcl. */
  119.             if (is(COMMA_TOK)) {
  120.                 error("Comma following function body ignored");
  121.                 get_token();
  122.             }
  123.             /* 2/16/89 */
  124.             prev_dcl = 0;
  125.             break;
  126.         }
  127.         else if (is(COMMA_TOK)) {
  128.             sd_end(scope, COMMA_TOK);
  129.             get_token();
  130.             /* 2/16/89 */
  131.             prev_dcl++;
  132.         }
  133.         else if (is(SEMICOLON_TOK)) {
  134.             sd_end(scope, SEMICOLON_TOK);
  135.             get_token();
  136.             /* 2/16/89 */
  137.             prev_dcl = 0;
  138.             break;
  139.         }
  140.         else {
  141.             err3(    "Unexpected end of declaration at '",
  142.                 pr_tok(),
  143.                 "', comma or semicolon expected");
  144.             needend(SEMICOLON_TOK);
  145.             /* 2/16/89 */
  146.             prev_dcl = 0;
  147.             break;
  148.         }
  149.     }
  150.     RETURN_VOID(fn_name);
  151. }
  152.  
  153.  
  154. /*
  155.     A program is nothing but a list of declarations and definitions.
  156. */
  157. void
  158. program(void)
  159. {
  160.     SL_NAME(fn_name, "program");
  161.     TRACETOK(fn_name);
  162.  
  163.     /* Get the first token of the program. */
  164.     get_token();
  165.  
  166.     for (;;) {
  167.         /* Not in function definition yet. */
  168.         func_def = FALSE;
  169.  
  170.         allow_mkeys();
  171.         if (is_type() || is(ID_TOK)) {
  172.             dcl(OUTER_SCOPE);
  173.         }
  174.         else if (is(EOP_TOK)) {
  175.             RETURN_VOID(fn_name);
  176.         }
  177.         else if (is(COMMA_TOK)) {
  178.             error("External comma ignored");
  179.             get_token();
  180.         }
  181.         else if (is(SEMICOLON_TOK)) {
  182.             error("External semicolon ignored");
  183.             get_token();
  184.         }
  185.         else if (is(RCURLY_TOK)) {
  186.             error("External '}' ignored");
  187.             get_token();
  188.         }
  189.         else if (is(LCURLY_TOK)) {
  190.             error("Check program structure: { in outer context");
  191.             get_token();
  192.         }
  193.         else {
  194.             err3(    "'",
  195.                 pr_tok(),
  196.                 "' ignored: outer declaration expected");
  197.             get_token();
  198.         }
  199.     }
  200. }
  201.  
  202. /* =============== Local routines =============== */
  203.  
  204. /*
  205.     Skip over any special modifier keywords used by
  206.     Microsoft C or Turbo C.
  207.  
  208.     Turboc:     asm interrupt
  209.     Microsoft:  fortran 
  210.     Both:       cdecl, far, huge, near, pascal
  211. */
  212. void
  213. allow_mkeys(void)
  214. {
  215.     char * p;
  216.  
  217.     TRACETOK("allow_mkeys");
  218.  
  219.     p = &t_symbol[0];
  220.     while (is(ID_TOK)) {
  221.         if (    str_eq(p, "asm") ||
  222.             str_eq(p, "cdecl") ||
  223.             str_eq(p, "far") ||
  224.             str_eq(p, "fortran") ||
  225.             str_eq(p, "interrupt") ||
  226.             str_eq(p, "huge") ||
  227.             str_eq(p, "near") ||
  228.             str_eq(p, "pascal")
  229.         ) {
  230.             get_token();
  231.         }
  232.         else {
  233.             break;
  234.         }
  235.     }
  236.     RETURN_VOID("allow_mkeys");
  237. }
  238.  
  239.  
  240. /*
  241.     Parse a formal paramenter list.
  242.     This may be an old style list (id's only) or a new style list.
  243.     The opening paren has already been read.
  244. */
  245. static void
  246. fp_list(en_scope scope)
  247. {
  248.     bool no_tail;
  249.     en_scope this_scope;
  250.  
  251.     SL_NAME(fn_name, "fp_list");
  252.     TRACETOK(fn_name);
  253.     TRACEPN(fn_name, printf("(%s)\n", pr_scope(scope)));
  254.  
  255.     /* Set scope to NULL_SCOPE on recursive entry to this routines. */
  256.     if (    scope == NULL_SCOPE ||
  257.         scope == NEW_FORMAL_SCOPE ||
  258.         scope == OLD_FORMAL_SCOPE) {
  259.         this_scope = NULL_SCOPE;
  260.     }
  261.     else {
  262.         this_scope = NEW_FORMAL_SCOPE;
  263.     }
  264.  
  265.     while (!is(RPAREN_TOK)) {
  266.  
  267.         /* Parse the id (old style) or the dcl (new style) */
  268.         allow_mkeys();
  269.         if(is_type() || is(ID_TOK)) {
  270.             sd_dcl(this_scope);
  271.             no_tail = type_head(this_scope);
  272.             if (!no_tail) {
  273.                 type_tail(this_scope);
  274.             }
  275.             sd_end(this_scope, SEMICOLON_TOK);
  276.         }
  277.         else if (is(DOTS3)) {
  278.             /* Variable number of parameters. */
  279.             get_token();
  280.         }
  281.         else {
  282.             goto bad_list;
  283.         }
  284.  
  285.         if (is(COMMA_TOK)) {
  286.             get_token();
  287.         }
  288.         else if (is(RPAREN_TOK)) {
  289.             break;
  290.         }
  291.         else {
  292.             goto bad_list;
  293.         }
  294.     }
  295.  
  296.     /* Eat the closing paren. */
  297.     get_token();
  298.     RETURN_VOID(fn_name);
  299.  
  300. bad_list:
  301.     err3(  "Unexpected '",
  302.         pr_tok(),
  303.         "' seen in formal parameter list");
  304.     needend(RPAREN_TOK);
  305.     RETURN_VOID(fn_name);
  306. }
  307.  
  308. /*
  309.     Parse the old style of declaration of argument types.
  310. */
  311.  
  312. static void
  313. t_list(void)
  314. {
  315.     SL_NAME(fn_name, "t_list");
  316.     TRACETOK(fn_name);
  317.  
  318.     while(is_type()) {
  319.         dcl(OLD_FORMAL_SCOPE);
  320.     }
  321.  
  322.     RETURN_VOID(fn_name);
  323. }
  324.  
  325. /* Parse a list of declarations of array bounds. */
  326. static void
  327. array(void)
  328. {
  329.     SL_NAME(fn_name, "array");
  330.     TRACETOK(fn_name);
  331.  
  332.     while (is(LBRACK_TOK)) {
  333.         get_token();
  334.         if (is(RBRACK_TOK)) {
  335.             /* [] is valid as an array bounds (sometimes). */
  336.             get_token();
  337.         }
  338.         else {
  339.             con_expr(RBRACK_TOK);
  340.             need(RBRACK_TOK);
  341.         }
  342.     }
  343.     RETURN_VOID(fn_name);
  344. }
  345.  
  346. /*
  347.     Parse a function declaration or definition.
  348.     The opening '(' of the formal parameter list has alread been eaten.
  349. */
  350. void
  351. function(en_scope scope)
  352. {
  353.     SL_NAME(fn_name, "function");
  354.     TRACETOK(fn_name);
  355.     TRACEPN(fn_name, printf("(%s)\n", pr_scope(scope)));
  356.  
  357.     /* Make sure a function definition is valid here. */
  358.     if (scope == STRUCT_SCOPE) {
  359.         error("Function defined in struct or union");
  360.     }
  361.     else if (scope != OUTER_SCOPE) {
  362.         error("Nested function definition");
  363.     }
  364.     else if (prev_dcl > 0) {
  365.         warning("Function not expected here");
  366.     }
  367.  
  368.     /* Parse the old-style list of parameter types. */
  369.     t_list();
  370.  
  371.     /*
  372.         We have a function DEFINITION.
  373.         Indicate that '}' ends dcl instead of ';'
  374.         WARNING:  t_list won't work if func_def is TRUE.
  375.     */
  376.     func_def = TRUE;
  377.  
  378.     if (!is(LCURLY_TOK)) {
  379.         error("Expecting '{' following formal declarations");
  380.         RETURN_VOID(fn_name);
  381.     }
  382.  
  383.     /* Set the